﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.IO.Ports;

namespace GroundStation
{
    public partial class Form1 : Form
    {
        Telemetry tele = new Telemetry();
        //private fdr.SDlogger sdlog = new fdr.SDlogger("");
        private fdr.SDlogger sdlog;

        private bool isfdr = false;
        private string format = "#,##0.00";

        public Form1()
        {
            InitializeComponent();
            string[] ports = SerialPort.GetPortNames();

            foreach (string port in ports)
            {
                chooseCOM.Items.Add(port);
                chooseCOM.SelectedItem = port;
            }

            textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> system inicializated.\r\n");
        }

        private void formGroundStation_FormClosed_1(object sender, FormClosedEventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> attempting application close.\r\n");
            if (tele != null)
            {
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> waiting for GS.\r\n");
                tele.Stop();
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> GS done.\r\n");
            }
            if (sdlog != null)
            {
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> wait for SDlogger.\r\n");
                sdlog.SDStop();
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> SDlogger done.\r\n");
            }
            textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> exitting.\r\n");
            this.Cursor = Cursors.Default; //this.Close();
        }

        /// <summary>
        /// Timer event to force new data display
        /// </summary>
        /// <param name="sender">object sender</param>
        /// <param name="e">event argument e</param>
        private void timer_Tick_1(object sender, EventArgs e)
        {
            if (isfdr)
            {
                if (sdlog.SDIsRunning())
                {
                    raw_state.Text = "Data processing!";
                    if (raw_state.Enabled)
                        raw_state.Enabled = false;
                    else raw_state.Enabled = true;
                }
                else
                {
                    if (!(rawFromFile.Enabled))
                    {
                        raw_state.Text = "not active";
                        rawFromFile.Enabled = true;
                        raw_state.Enabled = false;
                        directSD.Enabled = true;
                        logicalDrives.Enabled = true;
                        //~sdlog;
                    }
                }
            }
            lblTime.Text = TimeSpan.FromMilliseconds((double)tele.Time).ToString(@"h\:mm\:ss\.ff"); // needed by .net 3.5

            float a = 0;// tele.ImuAccX;
            //if (a != (float)0xff00)
                lblImuAccX.Text = tele.ImuAccX.ToString(format);// tele.ImuAccX.ToString(format);
            
            //if (a != (float)0xff00)
            lblImuAccY.Text = tele.ImuAccY.ToString(format);
            //if (a != (float)0xff00)
            lblImuAccZ.Text = tele.ImuAccZ.ToString(format);
            //if (a != (float)0xff00)
            lblImuArsX.Text = tele.ImuArsX.ToString(format);
            //if (a != (float)0xff00)
            lblImuArsY.Text = tele.ImuArsY.ToString(format);
            //if (a != (float)0xff00)
            lblImuArsZ.Text = tele.ImuArsZ.ToString(format);
            //if (a != (float)0xff00)
            lblImuAccMod1X.Text = tele.ImuAccMod1X.ToString(format);
            //if (a != (float)0xff00)
            lblImuAccMod1Y.Text = tele.ImuAccMod1Y.ToString(format);
            //if (a != (float)0xff00)
            lblImuAccMod2X.Text = tele.ImuAccMod2X.ToString(format);
            //if (a != (float)0xff00)
            lblImuAccMod2Y.Text = tele.ImuAccMod2Y.ToString(format);
            //if (a != (float)0xff00)
            lblImuPitch.Text = tele.ImuPitch.ToString(format);
            //if (a != (float)0xff00)
            lblImuRoll.Text = tele.ImuRoll.ToString(format);

            a = tele.TltPitch;
            if (!float.IsNaN(a))
            lblTltPitch.Text = a.ToString(format);
            a = tele.TltRoll;
            if (!float.IsNaN(a))
            lblTltRoll.Text = a.ToString(format);

            a = tele.Gps1Lat;
            if (!float.IsNaN(a))
                            lblGps1Lat.Text = a.ToString(format);
            a = tele.Gps1Lon;
            if (!float.IsNaN(a))
                    lblGps1Lon.Text = a.ToString(format);
            a = tele.Gps1Alt;
            if (!float.IsNaN(a))
                    lblGps1Alt.Text = a.ToString(format);
            a = tele.Gps1Speed;
            if (!float.IsNaN(a))
                    lblGps1Speed.Text = a.ToString(format);
            a = tele.Gps1VDOP;
            if (!float.IsNaN(a))
                    lblGps1VDOP.Text = a.ToString(format);
            a = tele.Gps1HDOP;
            if (!float.IsNaN(a))
                    lblGps1HDOP.Text = a.ToString(format);
            
            a = tele.Gps2Lat;
            if (!float.IsNaN(a))
                lblGps2Lat.Text = a.ToString(format);
            a = tele.Gps2Lon;
            if (!float.IsNaN(a))
                lblGps2Lon.Text = a.ToString(format);
            a = tele.Gps2Alt; 
            if (!float.IsNaN(a))
                lblGps2Alt.Text = a.ToString(format);
            a = tele.Gps2Speed;
            if (!float.IsNaN(a))
                lblGps2Speed.Text = a.ToString(format);
            a = tele.Gps2VDOP;
            if (!float.IsNaN(a))
                lblGps2VDOP.Text = a.ToString(format);
            a = tele.Gps2HDOP;
            if (!float.IsNaN(a))
                lblGps2HDOP.Text = a.ToString(format);
            

            a = tele.MagX;
            if (!float.IsNaN(a))
                lblMagX.Text = a.ToString(format);
            a = tele.MagY;
            if (!float.IsNaN(a))
                lblMagY.Text = a.ToString(format);
            a = tele.MagZ;
            if (!float.IsNaN(a))
                lblMagZ.Text = a.ToString(format);
            

            a = tele.AdcAlt;
            if (!float.IsNaN(a))
                lblAdcAlt.Text = a.ToString(format);
            a = tele.AdcAirSpeed;
            if (!float.IsNaN(a))
                lblAdcAirSpeed.Text = a.ToString(format);
            a = tele.AdcVario;
            if (!float.IsNaN(a))
                lblAdcVario.Text = a.ToString(format);
            a = tele.AdcTemp;
            if (!float.IsNaN(a))
                lblAdcTemp.Text = a.ToString(format);
            a = tele.AdcStatPress;
            if (!float.IsNaN(a))
                lblAdcStatPress.Text = a.ToString(format);
            a = tele.AdcDynPress;
            if (!float.IsNaN(a))
                lblAdcDynPress.Text = a.ToString(format);

            a = tele.Usr1Range;
            if (!float.IsNaN(a))
                lblUsr1Range.Text = a.ToString(format);
            a = tele.Usr2Range;
            if (!float.IsNaN(a))
                lblUsr2Range.Text = a.ToString(format);

            studentData.Text = tele.StudentData;

            // imu
            if ((tele.DevAviable & 0x01) != 0)
            {
                gbImu.BackColor = Color.GreenYellow;
            }
            else
            {
                gbImu.BackColor = Color.Red;
            }

            // tilt sensor
            if ((tele.DevAviable & 0x02) != 0)
            {
                gbTlt.BackColor = Color.GreenYellow;
            }
            else
            {
                gbTlt.BackColor = Color.Red;
            }

            // gps1
            if ((tele.DevAviable & 0x04) != 0)
            {
                gbGps1.BackColor = Color.GreenYellow;
            }
            else
            {
                gbGps1.BackColor = Color.Red;
            }

            // gps2
            if ((tele.DevAviable & 0x08) != 0)
            {
                gbGps2.BackColor = Color.GreenYellow;
            }
            else
            {
                gbGps2.BackColor = Color.Red;
            }

            // mag
            if ((tele.DevAviable & 0x10) != 0)
            {
                gbMag.BackColor = Color.GreenYellow;
            }
            else
            {
                gbMag.BackColor = Color.Red;
            }

            // adc
            if ((tele.DevAviable & 0x20) != 0)
            {
                gbAdc.BackColor = Color.GreenYellow;
            }
            else
            {
                gbAdc.BackColor = Color.Red;
            }

            // us range finder 1
            if ((tele.DevAviable & 0x40) != 0)
            {
                gbUsr1.BackColor = Color.GreenYellow;
            }
            else
            {
                gbUsr1.BackColor = Color.Red;
            }

            // us range finder 2
            if ((tele.DevAviable & 0x80) != 0)
            {
                gbUsr2.BackColor = Color.GreenYellow;
            }
            else
            {
                gbUsr2.BackColor = Color.Red;
            }
        }

        /// <summary>
        /// Start and stop data receiving by single button.
        /// </summary>
        /// <param name="sender">Event sender - button click</param>
        /// <param name="e">Event argument</param>
        private void buttonStart_Click(object sender, EventArgs e)
        {
            this.Cursor = Cursors.WaitCursor;
            //UseWaitCursor = true;
            if (chooseCOM.Enabled) // Application is not running
            {
                if (tele.Init(chooseCOM.SelectedItem.ToString(), asciLog.Checked)) // check right COM port and start app
                {
                    // log events and set button
                    textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> GS starts.\r\n");
                    buttonStart.Text = "Stop";
                    chooseCOM.Enabled = false;
                    asciLog.Enabled = false;
                }
                else
                {
                    textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> can't start - wrong COM port.\r\n"); // inform user about ...shit happens...
                }
            }
            else // Stop data storing
            {
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> attempting GS exit, saving .mat file.\r\n"); // log what is going to be done
                tele.Stop(); // stop telemetry
                textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> .mat file saved, exiting GS.\r\n"); // log events and set button
                buttonStart.Text = "Start";
                chooseCOM.Enabled = true;
                asciLog.Enabled = true;
            }
            this.Cursor = Cursors.Default;
        }

        private void rawFromFile_Click(object sender, EventArgs e)
        {
            if (directSD.Checked)
            {
                this.Cursor = Cursors.WaitCursor;
                if (logicalDrives.SelectedItem == null)
                {
                    textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> apropriate drive not selected.\r\n");
                }
                else
                {
                    textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> using " + logicalDrives.SelectedItem.ToString() + " as RAW source for datamining.\r\n");
                    sdlog = new fdr.SDlogger(logicalDrives.SelectedItem.ToString(), true);
                    isfdr = true;
                    
                    raw_state.Enabled = true;
                    rawFromFile.Enabled = false;
                    directSD.Enabled = false;
                    logicalDrives.Enabled = false;
                    //sdlog.SDRun();
                }
                this.Cursor = Cursors.Default;
            }
            else
            {
                OpenFileDialog openFileDialog1 = new OpenFileDialog();
                openFileDialog1.FilterIndex = 2;
                openFileDialog1.RestoreDirectory = true;

                if (openFileDialog1.ShowDialog() == DialogResult.OK)
                {
                    try
                    {
                        string file;
                        this.Cursor = Cursors.WaitCursor;
                        if ((file = openFileDialog1.FileName) != null)
                        {
                            textLog.AppendText(DateTime.Now.ToLongTimeString() + "=> processing SDlogger file " + file + ".\r\n");
                            sdlog = new fdr.SDlogger(file, false);
                            //raw_state.Text = "Data processing!";
                            directSD.Enabled = false;
                            raw_state.Enabled = true;
                            rawFromFile.Enabled = false;
                            isfdr = true;
                        }
                        this.Cursor = Cursors.Default;
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(DateTime.Now.ToLongTimeString() + "=> error: Could not read file from disk.\r\n\tOriginal error=> " + ex.Message);
                    }
                }
            }
        }

        private void directSD_CheckedChanged(object sender, EventArgs e)
        {
            if (directSD.Checked)
            {
                string[] drives = Environment.GetLogicalDrives();
                foreach (string drive in drives)
                {
                    System.IO.DriveInfo di = new System.IO.DriveInfo(drive);
                    if (di.DriveType == DriveType.Removable)
                    {
                        try
                        {
                            string dif = di.DriveFormat;
                        }
                        catch (Exception ex)
                        {
                            logicalDrives.Items.Add(drive);
                            logicalDrives.SelectedItem = drive;
                            textLog.AppendText(ex.ToString() + "\r\n");
                        }
                    }
                }
                rawFromFile.Text = "RAW SD!";
                logicalDrives.Visible = true;
            }
            else
            {
                rawFromFile.Text = "RAW file";
                logicalDrives.Visible = false;
            }
        }
    }
}
